package com.mspbots.web.core.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.mspbots.web.BaseService;
import com.mspbots.web.core.model.Message;
import com.mspbots.web.core.model.Tenant;
import com.mspbots.web.core.model.TimeEntry;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * TimeEntryAndMessageService
 *
 * @author Alex bob(https://github.com/vnobo)
 * @date Created by 2019/7/1
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class TimeEntryService extends BaseService {

    public Mono<JsonNode> selectPage(Map<String, Object> params) {

        params.put("descs", "entered_date");

        return this.coreClient.get("/tenant/user-time-entry/page", params)
                .flatMap(resultNode -> {
                    ObjectNode objectNode = resultNode.deepCopy();
                    JsonNode records = objectNode.get("records");

                    List<Mono<TimeEntry>> timeEntryMonos = new ArrayList<>();
                    records.elements().forEachRemaining(entryNode -> {
                        TimeEntry timeEntry = objectMapper.convertValue(entryNode, TimeEntry.class);
                        Mono<TimeEntry> timeEntryMono = this.coreClient.get("/tenant/" + timeEntry.getTenantId() + "/info",
                                null, Tenant.class)
                                .doOnNext(tenant -> timeEntry.setTenantName(tenant.getShortName()))
                                .flatMap(tenant -> this.coreClient.get("/teams/messages/list/",
                                        Map.of("timeEntryId", timeEntry.getCwTid(),
                                                "tenantId", tenant.getId()), Message[].class)
                                ).map(messages -> {
                                    timeEntry.setMessages(List.of(messages));
                                    return timeEntry;
                                });
                        timeEntryMonos.add(timeEntryMono);
                    });
                    return Flux.concat(timeEntryMonos)
                            .collectList()
                            .map(timeEntries -> objectNode.set("records", objectMapper.convertValue(timeEntries, JsonNode.class)));
                });

    }

    public Mono<JsonNode> selectList(Map<String, Object> params) {
        return this.coreClient.get("/tenant/user-time-entry/list-sort", params)
                .flatMap(resultNode -> {
                    List<Mono<TimeEntry>> timeEntryMonos = new ArrayList<>();
                    resultNode.elements().forEachRemaining(entryNode -> {
                        TimeEntry timeEntry = objectMapper.convertValue(entryNode, TimeEntry.class);
                        Mono<TimeEntry> timeEntryMono = this.coreClient.get("/tenant/" + timeEntry.getTenantId() + "/info", null, Tenant.class)
                                .doOnSuccess(tenant -> timeEntry.setTenantName(tenant.getShortName()))
                                .flatMap(tenant -> this.coreClient.get("/teams/messages/list/",
                                        Map.of("timeEntryId", timeEntry.getCwTid(),
                                                "tenantId", tenant.getId()), Message[].class)
                                ).map(messages -> {
                                    timeEntry.setMessages(List.of(messages));
                                    return timeEntry;
                                });
                        timeEntryMonos.add(timeEntryMono);
                    });
                    return Flux.concat(timeEntryMonos)
                            .collectList()
                            .map(timeEntries -> objectMapper.convertValue(timeEntries, JsonNode.class));
                });
    }
}
